package com.team.structure;

import java.util.LinkedList;
import java.util.List;

public class BlockingListSimple {
    private static final Object lock = new Object();

    private int limit;
    private List<Integer> list = new LinkedList<>();

    private BlockingListSimple(int limit) {
        this.limit = limit;
    }

    private int getLimit() {
        return limit;
    }

    /**
     * 入队列
     */
    private void enqueue(int value) {
        System.out.println("【生产者】开始插入数据：" + value);
        synchronized (lock) {
            while (list.size() == getLimit()) {
                try {
                    System.out.println("队列数据已满，【生产者】被阻塞..");
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if(list.size() == 0) {
                System.out.println("开始唤醒【消费者】删除数据...");
                lock.notify();
            }

            list.add(value);
        }
    }

    /**
     * 出队列
     */
    private void dequeue(int value) {
        System.out.println("【消费者】开始删除数据：" + value);
        synchronized (lock) {
            while(list.size() == 0) {
                try {
                    System.out.println("队列没有数据了，【消费者】被阻塞...");
                    lock.wait();
                    System.out.println("【消费者】继续执行...");
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if(list.size() == limit) {
                System.out.println("开始唤醒【生产者】添加数据...");
                lock.notify();
            }

            list.remove(0);
        }
    }

    public static void main(String[] args) {
        BlockingListSimple simpleList = new BlockingListSimple(5);
        Thread t1 = new Thread(() -> {
            for(int i = 0 ; ; i++) {
                simpleList.enqueue(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for(int i = 0; ; i++) {
                simpleList.dequeue(i);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();
    }
}
